﻿using System.Collections.Generic;
using UnityEngine;

namespace TC
{
    /// <summary>
    /// 蓝图里的调用堆栈，普通节点还是需要入栈的，因为有可能会有update
    /// 不需要监听条件改变，只跑一次逻辑
    /// </summary>
    public class Flow : Dispatcher
    {
        private List<IUpdate> updates = new List<IUpdate>();

        public override void Update(float delta)
        {
            base.Update(delta);

            foreach (var i in updates)
            {
                i.OnUpdate(delta);
            }
        }

        public override void Call(FlowNode node)
        {
            push(node);
            if (node is IUpdate)
            {
                updates.Add(node as IUpdate);
            }
            node.Execute(this);
        }

        public override void Call(FlowPort p)
        {
#if UNITY_EDITOR
            if (p.parent.HasBreak)
                Debug.Break();
#endif

            Port other = p.parent.graph.GetConnect(p);
            if (other == null)
            {
                End(0);
            }
            else
            {
                Call(other.parent);
            }
        }

        public override void End(int status)
        {
            FlowNode cur = callstack[callstack.Count - 1];
            callstack.Remove(cur);
            updates.Remove(cur as IUpdate);
            cur.Stop();

            while (callstack.Count > 0)
            {
                FlowNode next = callstack[callstack.Count - 1];
                if (next is IRepeat)
                {
                    (next as IRepeat).Next(status);
                    break;
                }
                else
                {
                    callstack.RemoveAt(callstack.Count - 1);
                    updates.Remove(cur as IUpdate);
                    next.Stop();
                }
            }

            //如果栈里没有控制节点了，说明本次end就是蓝图结束了
            if (callstack.Count == 0 && onComplete != null)
            {
                onComplete(status);
            }
        }

        public override void Destroy()
        {
            base.Destroy();

            FlowNode tmp = null;
            while (callstack.Count > 0)
            {
                tmp = callstack[callstack.Count - 1];
                callstack.RemoveAt(callstack.Count - 1);
                tmp.Stop();
            }
            updates.Clear();
            onComplete = null;
        }
    }
}
